package com.zboin.ucenter.auth;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zboin.ucenter.mapper.UserInfoMapper;
import com.zboin.ucenter.model.UserInfo;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import java.util.Collections;

/**
 * @author zhboom
 * @date 2025/7/21 23:11
 */
@Component
public class SmsAuthenticationProvider implements AuthenticationProvider {

    private final static String SMS_CODE_KEY = "SMS_CODE:";

    private final RedissonClient redissonClient;
    private final UserInfoMapper userInfoMapper;

    public SmsAuthenticationProvider(RedissonClient redissonClient, UserInfoMapper userInfoMapper) {
        this.redissonClient = redissonClient;
        this.userInfoMapper = userInfoMapper;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SmsAuthenticationToken authToken = (SmsAuthenticationToken) authentication;
        String phone = authToken.getPhone();
        String code = authToken.getCode();

        // 1. 校验Redis中的验证码
        String redisKey = SMS_CODE_KEY + phone;
        RBucket<String> bucket = redissonClient.getBucket(redisKey);
        String storedCode = bucket.get();

        if (!bucket.isExists() || storedCode == null || !storedCode.equals(code)) {
            throw new BadCredentialsException("Invalid SMS code");
        }

        // 2. 获取用户信息
        UserInfo userInfo = userInfoMapper.selectOne(
                new QueryWrapper<UserInfo>().eq("phone",  phone));

        // 3. 创建认证结果
        SmsAuthenticationToken authenticatedToken = new SmsAuthenticationToken(userInfo, code, Collections.emptyList());
        authenticatedToken.setAuthenticated(true);

        return authenticatedToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return SmsAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
